package com.mybatis.rcache;

import com.rcache.core.Element;
import com.rcache.core.cache.BaseCache;
import com.rcache.core.cache.Rcache;
import com.rcache.core.cache.strategy.FIFOCache;
import com.rcache.core.exception.ConfigurationException;
import com.rcache.core.manager.CacheManager;
import org.apache.ibatis.cache.Cache;

import java.util.concurrent.locks.ReadWriteLock;

/**
 * @desc 连接mybatis 的抽象缓存接口
 * @author gzy
 * @time 2022-06-05
 */
public abstract class AbstractRcacheCache implements Cache {

    /**
     * @desc 缓存管理器
     */
    protected static CacheManager CACHE_MANAGER;

    static {
        try {
            CACHE_MANAGER = CacheManager.newInstance();
        } catch (ConfigurationException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @desc 缓存的id也就是名字
     */
    protected final String id;

    /**
     * @desc 缓存示例对象
     */
    protected Rcache cache;
    
    /**
     * @param id
     */
    public AbstractRcacheCache(final String id) {
        if (id == null) {
            throw new IllegalArgumentException("Cache instances require an ID");
        }
        this.id = id;
    }

    /**
     * @desc 清空缓存
     */
    @Override
    public void clear() {
        cache.clear();
    }

    /**
     * @desc 获取缓存名称
     * @return
     */
    @Override
    public String getId() {
        return id;
    }

    /**
     * @desc 获取缓存的key
     * @param key The key
     * @return
     */
    @Override
    public Object getObject(Object key) {
        if (cache==null){
            setMemoryStoreEvictionPolicy("default");
        }
        Element value = cache.get(key);
        if (value==null){
            return null;
        }
        return value.getObjectValue();
    }

    /**
     * 获取缓存中数量
     */
    @Override
    public int getSize() {
        return cache.getSize();
    }

    /**
     * @desc  向缓存追加元素
     * @param key
     * @param value
     */
    @Override
    public void putObject(Object key, Object value) {
        cache.put(key,value);
    }

    /**
     * @desc 移除指定元素
     * @param key The key
     * @return
     */
    @Override
    public Object removeObject(Object key) {
        Object obj = getObject(key);
        cache.remove(key);
        return obj;
    }

    /**
     * @desc  释放锁
     * @param key
     */
    public void unlock(Object key) {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof Cache)) {
            return false;
        }

        Cache otherCache = (Cache) obj;
        return id.equals(otherCache.getId());
    }

    /**
     * @desc 重写hashCode方法，安装缓存名称来计算
     * @return
     */
    @Override
    public int hashCode() {
        return id.hashCode();
    }

    /**
     * @desc 得到读写锁
     * @return
     */
    @Override
    public ReadWriteLock getReadWriteLock() {
      return null;
    }


    @Override
    public String toString() {
        return "EHCache {"
                + id
                + "}";
    }

    /**
     * @desc 设置最大空闲时间
     * @param timeToIdleSeconds
     */
    public void setTimeToIdleSeconds(long timeToIdleSeconds) {
        ((BaseCache)cache).setMaxTimeToIdle((int) timeToIdleSeconds);
    }

    /**
     * @desc 设置最大存活时间
     * @param timeToLiveSeconds
     */
    public void setTimeToLiveSeconds(long timeToLiveSeconds) {
        ((BaseCache)cache).setMaxTimeToLive((int) timeToLiveSeconds);
    }

    /**
     * @desc 设置最大数量
     * @param maxEntriesLocalHeap
     */
    public void setMaxEntriesLocalHeap(long maxEntriesLocalHeap) {
        ((BaseCache)cache).setMaxElements((int) maxEntriesLocalHeap);
    }

    /**
     * @desc 设置本地缓存最大数量
     * @param maxEntriesLocalDisk
     */
    public void setMaxEntriesLocalDisk(long maxEntriesLocalDisk) {
//        cache.setmaxEntriesLocalDisk);

    }

    /**
     * @desc 设置淘汰策略
     * @param memoryStoreEvictionPolicy
     */
    public void setMemoryStoreEvictionPolicy(String memoryStoreEvictionPolicy) {
        try {
            CACHE_MANAGER=CacheManager.newInstance();
        } catch (ConfigurationException e) {
            throw new RuntimeException(e);
        }
        cache=CACHE_MANAGER.getCache(memoryStoreEvictionPolicy);
    }

}
